{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "intervalMinutes = 5\n",
    "datasetName = 'sample_data'\n",
    "binsPerDay = ( 60/ intervalMinutes) * 24\n",
    "binsPerWeek = binsPerDay * 7\n",
    "wmaWindowSize = (2 * (60 / intervalMinutes)) + 1\n",
    "numWeeks = 4\n",
    "daysPerWeek = 7"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "library(jsonlite)\n",
    "library(readr)\n",
    "\n",
    "pad <- function(data, leftPadSize, rightPadSize){\n",
    "    newLength = leftPadSize + length(data) + rightPadSize;\n",
    "    result <- c(newLength)\n",
    "    for (i in 1:newLength) { \n",
    "        result[i + leftPadSize] <- data[i]\n",
    "    }\n",
    "    result\n",
    "}\n",
    "\n",
    "smoothWma <- function(data, width) {\n",
    "    halfWidth <- width / 2\n",
    "    height <- halfWidth + 1\n",
    "    totalWeight <- height * height\n",
    "    newLength <- length(data) - width + 1\n",
    "    result <- c(newLength) \n",
    "    \n",
    "    for (i in 1:newLength) { \n",
    "        sum = 0.0\n",
    "        jCenter <- i + halfWidth;\n",
    "        for (j in jCenter - halfWidth:jCenter + halfWidth) { \n",
    "            weight <- height - abs(jCenter - j)\n",
    "            sum <- sum + weight * data[j]\n",
    "        }\n",
    "        result[i] <- sum / totalWeight\n",
    "    }\n",
    "    result\n",
    "}\n",
    "\n",
    "plus <- function(data, amount){\n",
    "    result <- c(length(data))\n",
    "    for (i in 1:length(data)) { \n",
    "        result[i] <- data[i] + amount\n",
    "      }\n",
    "   result\n",
    "}\n",
    "\n",
    "toLogDailyAndRemainder <- function(logData, logTrend, logWeekly) {\n",
    "    result <- c(length(logData))\n",
    "    for (i in 1:length(logData)) { \n",
    "        result[i] <- logData[i] - (logTrend[i] + logWeekly[i])\n",
    "    }\n",
    "    result\n",
    "}\n",
    "\n",
    "toLogDowSubcycles <- function(data) {\n",
    "    numWeeks <- numWeeks\n",
    "    binsPerDay <- binsPerDay\n",
    "    binsPerWeek <- binsPerWeek\n",
    "    result <- matrix(nrow = daysPerWeek, ncol= numWeeks * binsPerDay, dimnames = list(c(), c()))\n",
    "    for (i in 1:daysPerWeek) { \n",
    "        dataOffset <- (i-1) * binsPerDay\n",
    "        for (j in 1:numWeeks) { \n",
    "            dataStart <- ((j-1) * binsPerWeek) + dataOffset\n",
    "            resultStart <- (j-1) * binsPerDay\n",
    "            for (k in 1:binsPerDay) { \n",
    "                result[i, (resultStart + k)] <- data[(dataStart + k)]\n",
    "            }\n",
    "        }\n",
    "    }\n",
    "    result\n",
    "}\n",
    "\n",
    "toLogDaily <- function(logDowSubcycles) {\n",
    "    np <- binsPerDay\n",
    "    numWeeks <- numWeeks\n",
    "    numBinsPerDay <- binsPerDay\n",
    "    numBinsPerWeek <- binsPerWeek\n",
    "    numBinsPerDow <- numWeeks * numBinsPerDay\n",
    "    logDowSeasonals <- matrix(nrow = daysPerWeek, ncol= numWeeks * binsPerDay, dimnames = list(c(), c()))    \n",
    "    for (i in 1:daysPerWeek) { \n",
    "        logDowSeasonals[i,] = decompose(logDowSubcycles[i,], numBinsPerDay, numBinsPerDow)$time.series[, 'seasonal']\n",
    "    }\n",
    "    resultSize <- daysPerWeek * numBinsPerDow\n",
    "    result <- c(resultSize)\n",
    "    for (i in 1:numWeeks) { \n",
    "        for (j in 1:daysPerWeek) { \n",
    "            for (k in 1:numBinsPerDay) { \n",
    "                resultIndex <- ((i-1) * numBinsPerWeek) + ((j-1) * numBinsPerDay) + k\n",
    "                subcycleIndex <- ((i-1) * numBinsPerDay) + k\n",
    "                result[resultIndex] <- logDowSeasonals[j, subcycleIndex]\n",
    "            }\n",
    "        }\n",
    "    } \n",
    "    result\n",
    "}\n",
    "\n",
    "\n",
    "toTrend <- function(logTrend) {\n",
    "    trend <- plus(exp(logTrend), -1)\n",
    "    padSize <- trunc(wmaWindowSize / 2)\n",
    "    padded <- pad(trend, padSize, padSize)\n",
    "    for (i in 1:padSize) {\n",
    "        padded[i] <- trend[1]\n",
    "        padded[(length(padded) - padSize)+ i] <- trend[length(trend) - 1]\n",
    "      }\n",
    "    smoothWma(padded, wmaWindowSize)\n",
    "}\n",
    "\n",
    "toSeasonal <- function(logSeasonal) {\n",
    "    seasonal <- plus(exp(logSeasonal), -1)\n",
    "    padSize <- trunc(wmaWindowSize / 2)\n",
    "    padded <- pad(seasonal, padSize, padSize)\n",
    "    for (i in 1:padSize) {\n",
    "        padded[i] <- seasonal[(length(seasonal) - padSize) + i]\n",
    "    }\n",
    "    for (i in 1:padSize) {\n",
    "        padded[length(padded) - padSize + i] <- seasonal[i]\n",
    "    }\n",
    "    smoothWma(padded, wmaWindowSize)\n",
    "}\n",
    "\n",
    "\n",
    "fitS1Model <- function(values) {\n",
    "    fit <- decompose(log(plus(values, 1)), binsPerWeek, length(values))\n",
    "    trend <- toTrend(fit$time.series[, 'trend'])\n",
    "    seasonal <- toSeasonal(fit$time.series[, 'seasonal'])\n",
    "    result <- list(trend=trend,seasonal=seasonal)\n",
    "    result\n",
    "}\n",
    "\n",
    "fitS2Model <- function(values) {\n",
    "    binsPerDay <- binsPerDay\n",
    "    binsPerWeek <- binsPerWeek\n",
    "    logData <- log(plus(values, 1))\n",
    "    stlResult1 <- decompose(logData, binsPerDay, length(values))\n",
    "    stlResult2 <- decompose(stlResult1$time.series[, 'trend'], binsPerWeek, length(values))\n",
    "    logTrend <- stlResult2$time.series[, 'trend']\n",
    "    logWeekly <- stlResult2$time.series[, 'seasonal']\n",
    "    logDailyAndRemainder <- toLogDailyAndRemainder(logData, logTrend, logWeekly)\n",
    "    logDowSubcycles <- toLogDowSubcycles(logDailyAndRemainder)\n",
    "    logDaily <- toLogDaily(logDowSubcycles)\n",
    "    trend <- toTrend(logTrend)\n",
    "    weekly <- toSeasonal(logWeekly)\n",
    "    daily <- toSeasonal(logDaily)\n",
    "    model <- list(trend = trend, daily = daily, weekly = weekly)\n",
    "    write.model(model, \"stl-model\")\n",
    "}\n",
    "\n",
    "estimate <- function(data) {\n",
    "    if (binsPerDay <= 1) {\n",
    "        fitS1Model(data)\n",
    "    }\n",
    "    else {\n",
    "        fitS2Model(data)\n",
    "    }\n",
    "}\n",
    "\n",
    "decompose <- function(data, np, n) {\n",
    "    data.ts <- ts(data, frequency = np)\n",
    "    fit <- stl(data.ts, s.window = 10 * n + 1, robust = TRUE)\n",
    "    fit\n",
    "}\n",
    "\n",
    "read.data <- function(name) {\n",
    "    path <- paste(name, \".csv\", sep=\"\")\n",
    "    read.csv(path, header=TRUE)\n",
    "}\n",
    "\n",
    "\n",
    "write.model <- function(model, name) {\n",
    "    dir.create(file.path(\"out/models\"), recursive=TRUE, showWarnings=FALSE)\n",
    "    path <- paste(\"out/models/\", name, \".json\", sep=\"\")\n",
    "    json <- toJSON(model)\n",
    "    write_json(model, path)\n",
    "}\n",
    "\n",
    "path <- paste(\"data/\", datasetName, sep=\"\")\n",
    "data <- read.data(path)\n",
    "current <- data[,2]\n",
    "midpointModel <- estimate(current)\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "R",
   "language": "R",
   "name": "ir"
  },
  "language_info": {
   "codemirror_mode": "r",
   "file_extension": ".r",
   "mimetype": "text/x-r-source",
   "name": "R",
   "pygments_lexer": "r",
   "version": "3.4.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
